


#ifndef LIB_SM3_H
#define LIB_SM3_H

#include <string.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif


/**
 * @brief Flag indicating if system is big endian
 */
#define LIB_SM3_IS_BIG_ENDIAN	1


/**
 * @brief Size of SM3 hash digest in bytes (256 bits)
 */
#define LIB_SM3_DIGEST_SIZE		32


/**
 * @brief Size of internal block processed by SM3 in bytes (512 bits)
 */
#define LIB_SM3_BLOCK_SIZE		64


/**
 * @brief Number of 32-bit words in SM3 internal state
 */
#define LIB_SM3_STATE_WORDS		8


/**
 * @brief Size of HMAC output in bytes, same as digest size
 */
#define LIB_SM3_HMAC_SIZE		(LIB_SM3_DIGEST_SIZE)


/**
 * @brief Context structure for SM3 hash computation
 */
typedef struct {
	uint32_t digest[LIB_SM3_STATE_WORDS];  /* Internal state array */
	uint64_t nblocks;                      /* Number of blocks processed */
	uint8_t block[LIB_SM3_BLOCK_SIZE];     /* Partial block buffer */
	uint32_t num;                          /* Number of bytes in partial block */
} LIB_SM3_CTX;


/**
 * @brief Initialize SM3 hash context
 * @param ctx Context to initialize
 */
void XMen_lib_sm3_init(LIB_SM3_CTX *ctx);


/**
 * @brief Update SM3 hash with input data
 * @param ctx Hash context
 * @param data Input data buffer
 * @param datalen Length of input in bytes
 */
void XMen_lib_sm3_update(LIB_SM3_CTX *ctx, const uint8_t *data, uint32_t datalen);


/**
 * @brief Finalize SM3 hash computation
 * @param ctx Hash context
 * @param dgst Output buffer for hash value (32 bytes)
 */
void XMen_lib_sm3_finish(LIB_SM3_CTX *ctx, uint8_t dgst[LIB_SM3_DIGEST_SIZE]);


/**
 * @brief Compute SM3 hash of message in one call
 * @param data Input message buffer
 * @param datalen Length of message in bytes
 * @param dgst Output buffer for hash value (32 bytes)
 */
void XMen_lib_sm3_digest(const uint8_t *data, uint32_t datalen, uint8_t dgst[LIB_SM3_DIGEST_SIZE]);


/**
 * @brief Process multiple complete blocks with SM3 compression function
 * @param digest Hash state array
 * @param data Input data buffer
 * @param blocks Number of blocks to process
 */
void XMen_lib_sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, uint32_t blocks);


/**
 * @brief Context structure for HMAC-SM3 operation
 */
typedef struct {
	LIB_SM3_CTX lib_sm3_ctx;              /* SM3 context for hash computations */
	uint8_t key[LIB_SM3_BLOCK_SIZE];      /* HMAC key after processing */
} LIB_SM3_HMAC_CTX;


/**
 * @brief Initialize HMAC-SM3 context
 * @param ctx HMAC context to initialize
 * @param key HMAC key buffer
 * @param keylen Length of key in bytes
 */
void XMen_lib_sm3_hmac_init(LIB_SM3_HMAC_CTX *ctx, const uint8_t *key, uint32_t keylen);


/**
 * @brief Update HMAC-SM3 with input data
 * @param ctx HMAC context
 * @param data Input data buffer
 * @param datalen Length of input in bytes
 */
void XMen_lib_sm3_hmac_update(LIB_SM3_HMAC_CTX *ctx, const uint8_t *data, uint32_t datalen);


/**
 * @brief Finalize HMAC-SM3 computation
 * @param ctx HMAC context
 * @param mac Output buffer for HMAC value (32 bytes)
 */
void XMen_lib_sm3_hmac_finish(LIB_SM3_HMAC_CTX *ctx, uint8_t mac[LIB_SM3_HMAC_SIZE]);


/**
 * @brief Compute HMAC-SM3 in one call
 * @param key HMAC key buffer
 * @param keylen Length of key in bytes
 * @param data Input data buffer
 * @param datalen Length of input in bytes
 * @param mac Output buffer for HMAC value (32 bytes)
 */
void XMen_lib_sm3_hmac(const uint8_t *key, uint32_t keylen,
	const uint8_t *data, uint32_t datalen,
	uint8_t mac[LIB_SM3_HMAC_SIZE]);


/**
 * @brief Context structure for SM3-KDF (Key Derivation Function)
 */
typedef struct {
	LIB_SM3_CTX lib_sm3_ctx;              /* SM3 context for hash operations */
	uint32_t outlen;                       /* Desired output length in bytes */
} LIB_SM3_KDF_CTX;


/**
 * @brief Initialize SM3-KDF context
 * @param ctx KDF context to initialize
 * @param outlen Desired length of output key material in bytes
 */
void XMen_lib_sm3_kdf_init(LIB_SM3_KDF_CTX *ctx, uint32_t outlen);


/**
 * @brief Update SM3-KDF with input data
 * @param ctx KDF context
 * @param data Input data buffer
 * @param datalen Length of input in bytes
 */
void XMen_lib_sm3_kdf_update(LIB_SM3_KDF_CTX *ctx, const uint8_t *data, uint32_t datalen);


/**
 * @brief Finalize SM3-KDF and output derived key material
 * @param ctx KDF context
 * @param out Output buffer for derived key material
 */
void XMen_lib_sm3_kdf_finish(LIB_SM3_KDF_CTX *ctx, uint8_t *out);


#ifdef __cplusplus
}
#endif
#endif
